package com.hwtx.form.domain.handle.core;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hwtx.form.domain.def.FormConfigExt;
import com.hwtx.form.domain.def.meta.config.FormComponentConfig;
import com.hwtx.form.domain.ds.DataSourceContextHolder;
import com.hwtx.form.domain.handle.SelectItemsInfo;
import com.hwtx.form.domain.meta.FormConfigMeta;
import com.hwtx.form.domain.vo.FormConfigQueryVo;
import com.hwtx.form.persistence.entity.I18nMessage;
import com.hwtx.form.util.FormUtil;
import jakarta.annotation.Resource;
import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.CacheManager;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;

import static com.hwtx.form.domain.FormConstants.*;
import static com.hwtx.form.domain.def.meta.config.FormComponentConfig.getFormComponentConfig;
import static com.hwtx.form.util.FormUtil.getFormConfigExt;

@Slf4j
public class DefaultFormBaseHandle {
    @Resource
    protected FormConfigMeta formConfigMeta;
    @Resource
    private CacheManager cacheManager;

    void checkJdbcTemplate(String ds) {
        if (StringUtils.isBlank(ds)) {
            ds = DEFAULT_DS_NAME;
        }
        if (!Objects.equals(DEFAULT_DS_NAME, ds)) {
            DataSourceContextHolder.setDataSourceKey(JDBC_PREFIX + ds);
        } else {
            DataSourceContextHolder.setDataSourceKey(DEFAULT_DS_NAME);
        }
    }

    void handleI18n(I18nMessage i18nMessage) {
        org.springframework.cache.Cache cache = cacheManager.getCache(I18n_CACHE_KEY);
        if (cache != null && i18nMessage != null) {
            if (i18nMessage.getId() == null) {
                cache.put(i18nMessage.getMessageKey(), i18nMessage);
            } else {
                cache.evictIfPresent(i18nMessage.getMessageKey());
            }
        }
    }

    SelectItemsInfo getFormItems(Long formId, boolean all) throws ExecutionException {
        List<FormConfigQueryVo> formConfigQueries = formConfigMeta.getFormConfigQueries(formId);
        Map<String, List<SelectItemsInfo.SelectItemInfo>> tableItems = Maps.newHashMap();
        List<SelectItemsInfo.SelectItemInfo> noTableItems = Lists.newArrayList();
        Map<String, Map<String, String>> uniqueItems = Maps.newHashMap();
        formConfigQueries.stream().filter(item -> {
            boolean show = Objects.equals(item.getIsFormShow(), (byte) 1);
            if (!show) {
                return Objects.equals(item.getFormController(), FormComponentType.FORM_COM_HIDDEN.getValue())
                        || Objects.equals(item.getFormController(), FormComponentType.FORM_COM_API_INVOKE.getValue());
            }
            if (all) {
                return true;
            }
            return true;
        }).forEach(item -> {
            Integer controller = FormUtil.getController(item, FORM);
            SelectItemsInfo.SelectItemInfo selectItemsInfo;
            boolean isApiInvoke = Objects.equals(controller, FormComponentType.FORM_COM_API_INVOKE.getValue());
            String field = item.getField();
            String name = item.getName();
            if (Objects.equals(field, DefaultColumn.id.name())) {
                name = item.getTableName() + "_" + field;
            }
            if (controller == null) {
                selectItemsInfo = SelectItemsInfo.SelectItemInfo.builder().field(field).name(name).build();
            } else {
                ComponentConfigInfo componentConfigInfo = getComponentConfigInfo(controller, item, FORM);
                selectItemsInfo = SelectItemsInfo.SelectItemInfo.builder().field(field).name(name)
                        .addFields(componentConfigInfo.addFields).isApiInvoke(isApiInvoke)
                        .mask(Objects.equals(item.getFormController(), FormComponentType.FORM_COM_PWD.getValue()))
                        .formComponentConfig(componentConfigInfo.formComponentConfig).comExt(componentConfigInfo.comExt).build();
            }
            if (StringUtils.isNotBlank(item.getTableName())) {
                tableItems.compute(item.getTableName(), (k, v) -> {
                    if (v == null) {
                        v = Lists.newArrayList();
                    }
                    v.add(selectItemsInfo);
                    return v;
                });
            } else {
                noTableItems.add(selectItemsInfo);
            }
            if (Objects.equals(item.getIsUnique(), (byte) 1)) {
                uniqueItems.compute(item.getTableName(), (k, v) -> {
                    if (v == null) {
                        v = Maps.newHashMap();
                    }
                    v.put(item.getField(), item.getDescription());
                    return v;
                });
            }
        });
        return SelectItemsInfo.builder().tableItems(tableItems).noTableItems(noTableItems).uniqueItems(uniqueItems).build();
    }

    protected ComponentConfigInfo getComponentConfigInfo(Integer controller, FormConfigQueryVo vo, String type) {
        ComponentConfigInfo.ComponentConfigInfoBuilder builder = ComponentConfigInfo.builder();
        FormComponentConfig formComponentConfig = getFormComponentConfig(controller);
        if (formComponentConfig != null) {
            FormConfigExt formConfigExt = getFormConfigExt(vo.getExt());
            if (formConfigExt != null) {
                FormConfigExt.FormConfigCtr formConfigCtr = FormUtil.getFormConfigCtr(type, formConfigExt);
                if (formConfigCtr != null) {
                    builder.addFields(formComponentConfig.getFields(formConfigCtr.getComExt()));
                    builder.comExt = formConfigCtr.getComExt();
                    builder.formComponentConfig = formComponentConfig;
                }
            }
        }
        return builder.build();
    }

    @Getter
    @Builder
    public static class ComponentConfigInfo {
        Map<String, List<String>> addFields;
        FormComponentConfig formComponentConfig;
        Map<String, Object> comExt;
    }

}
